package puzzle.devtools;

import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.AWTGLCanvas;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.Font;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.openal.SoundStore;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.Log;

/** 
 * A simple canvas for integrating Slick graphics
 * into a Swing environment, using AWTGLCanvas.
 * <p/>
 * Most of this code is from Kevin's ParticleCanvas 
 * (part of Pedigree) and from GameContainer. 
 *
 * @author davedes
 */
public abstract class SlickCanvas extends AWTGLCanvas {
     
  /** The last update time */
  private long lastTime;
  
  /** Graphics for drawing. */
  private Graphics graphics;
  
  /** The font used to display info on the canvas */
  private Font defaultFont;
  
  /** The frame rate */
  private int fps;
  
  /** The last update of fps */
  private int lastUpdate;
  
  /** The number of frames since last count */
  private int frameCount;
  
  /** Whether to display the frame rate. */
  protected boolean showFPS = true;
  
  /** The background Color for the Slick Graphics context. */
  private Color bgColor = null;
  
  private int targetFPS = -1;
  
  /** Constructs a new SlickCanvas. */
  protected SlickCanvas() throws LWJGLException {
    super();
  }
  
  /** 
   * Almost exclusively from Pedigree's ParticleCanvas.
   * @see org.lwjgl.opengl.AWTGLCanvas#initGL() 
   */
  protected void initGL() {    
    //gets canvas size
    int width = getWidth();
    int height = getHeight();
    
    TextureLoader.get().clear();
    SoundStore.get().clear();

    Log.info("Starting canvas display "+width+"x"+height);
    String extensions = GL11.glGetString(GL11.GL_EXTENSIONS);
    
    //vertical sync
    Display.setVSyncEnabled(true);

    //see GameContainer.initGL()
    ////// START GL INIT
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glShadeModel(GL11.GL_SMOOTH);        
    GL11.glDisable(GL11.GL_DEPTH_TEST);
    GL11.glDisable(GL11.GL_LIGHTING);                    
    
    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                
    GL11.glClearDepth(1);                                       
    
    GL11.glEnable(GL11.GL_BLEND);
    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    
    GL11.glViewport(0,0,width,height);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GL11.glOrtho(0, width, height, 0, 1, -1);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    ////// END GL INIT
    
    //input can be added here if you need it
    //or you can add your own AWT mouse/key listeners
    //...
    //...
    
    //see GameContainer.initSystem()
    graphics = new Graphics(width, height);
    
    //sets Slick background
    if (bgColor!=null)
      graphics.setBackground(bgColor);
      
    try {
      initSystem();
    }
    catch (SlickException e) {
      Log.error(e);
    }
  }
  
  /** 
   * Almost exclusively from Pedigree's ParticleCanvas.
   * @see org.lwjgl.opengl.AWTGLCanvas#paintGL() 
   */
  protected void paintGL() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
    GL11.glLoadIdentity();
    
    //renders the Slick content
    render(graphics);
    
    //draw fps
    if (showFPS)
      graphics.drawString("FPS: "+fps, 10, 10);
    
    //ie: call this method again
    try {
      swapBuffers();
      if (isVisible()) {
        repaint();
      }
    } 
    catch (Exception e) {
      e.printStackTrace();
      System.exit(0);
    }
    
    //gets delta
    long thisTime = ((Sys.getTime() * 1000) / Sys.getTimerResolution());
    long delta = thisTime - lastTime;
    lastTime = thisTime;
        
    //updates FPS
    frameCount++;
    lastUpdate -= delta;
    if (lastUpdate < 0) {
      fps = frameCount;
      frameCount = 0;
      lastUpdate = 1000;
    }
    
    //update the Slick content
    update((int)delta);
    
    if (targetFPS!=-1) {
      Display.sync2(targetFPS); 
    }
  }
  
  public void setTargetFPS(int t) {
    targetFPS = t;
  }
  
  public int getTargetFPS() {
    return targetFPS;
  }
  
  /** Called to render the canvas. */
  abstract void render(Graphics g);
  
  /** Called to update the canvas. */
  abstract void update(int delta);
  
  /** Called to set up resources (fonts, images, sounds, etc). */
  abstract void initSystem() throws SlickException;
  
  /** Sets the background for the Slick graphics. */
  public void setSlickBackground(Color c) {
    bgColor = c;
    if (graphics!=null) 
      graphics.setBackground(bgColor);
  }
  
  /** Gets the background for the Slick graphics. */
  public Color getSlickBackground() {
    return bgColor;
  }
}